package slu.appli.tools.parser.stringparser.impl.treemodel;

import java.util.ArrayList;
import java.util.List;

import slu.appli.tools.parser.stringparser.StringParserException;
import slu.appli.tools.parser.stringparser.interfaces.model.GroupInterface;
import slu.appli.tools.parser.stringparser.interfaces.model.ModelReaderInterface;
import slu.appli.tools.parser.stringparser.interfaces.model.ModelReaderListenerInterface;

public class BasicTreeModelReader 
implements ModelReaderInterface {
	private GroupInterface root = null;
	private boolean stopped = false;
	private boolean paused = false;
	private int readPosition = 0;
	private int restartPosition = 0;
	private List<ModelReaderListenerInterface> listeners = new ArrayList<ModelReaderListenerInterface>();
	
	public BasicTreeModelReader(GroupInterface root) {
		super();
		this.root = root;
	}

	public void addModelReaderListener(ModelReaderListenerInterface listener) {
		this.listeners.add(listener); 
	}
	
	private void fireReaderStarted() {
		for (ModelReaderListenerInterface listener : this.listeners) {
			listener.readerStarted(this);
		}
	}
	
	private void fireItemReaded(Object item) {
		for (ModelReaderListenerInterface listener : this.listeners) {
			listener.itemReaded(item);
		}
	}
	
	private void fireGroupReaded(BasicTreeNode node) {
		for (ModelReaderListenerInterface listener : this.listeners) {
			listener.groupReaded(node);
		}
	}
	
	private void fireReaderEnded() {
		for (ModelReaderListenerInterface listener : this.listeners) {
			listener.readerEnded();
		}
	}
	
	private void fireReaderRestarted() {
		for (ModelReaderListenerInterface listener : this.listeners) {
			listener.readerRestarted();
		}
	}
	
	private void fireStopPerformed() {
		for (ModelReaderListenerInterface listener : this.listeners) {
			listener.stopPerformed();
		}
	}
	
	private void firePausePerformed() {
		for (ModelReaderListenerInterface listener : this.listeners) {
			listener.pausePerformed();
		}
	}
	
	private void processNode(GroupInterface node) {
		for (int j = 0; j< node.getOccurs(); j++) {
			for (int i = 0; i < node.getChildCount(); i ++) {
				if (this.stopped == true) {
					this.restartPosition = -1;
					return;
				}
				if (this.paused == true) {
					this.restartPosition = this.readPosition;
					return;
				}
				this.readPosition++;
				if (this.restartPosition > -1 && this.restartPosition == this.readPosition) {
					this.restartPosition = -1;
					this.fireReaderRestarted();
				}
				Object item = node.getChildAt(i);
				if (item instanceof BasicTreeNode) {
					BasicTreeNode nodeItem = (BasicTreeNode) item;
					if (this.restartPosition <= this.readPosition) {
						this.fireGroupReaded(nodeItem);
					}
					this.processNode(nodeItem);
				}
				else {
					if (this.restartPosition <= this.readPosition) {
						this.fireItemReaded(item);
					}
				}
			}
		}
		// permet de traiter la pause sur le dernier item du model
		if (this.paused == true) {
			this.restartPosition = this.readPosition;
			return;
		}
	}
	
	public void read() {
		this.stopped = false;
		this.paused = false;
		this.readPosition = 0;
		this.restartPosition = -1;
		this.fireReaderStarted();
		this.processNode(this.root);
		if (!this.paused) this.fireReaderEnded();
	}

	public void pause() {
		if (this.paused) return;
		this.paused = true;
		this.firePausePerformed();
	}

	public void stop() {
		if (this.stopped) return;
		this.stopped = true;
		this.fireStopPerformed();
	}

	public void restart() {
		if (!this.paused) throw new StringParserException("Le lecteur n'est pas en pause");
		this.paused = false;
		this.readPosition = 0;
		this.processNode(this.root);
		if (!this.paused) this.fireReaderEnded();
	}

	public boolean isPaused() {
		return this.paused;
	}

}
